package com.ankang.controller;

import com.ankang.entity.ChannelLevel;
import com.ankang.entity.TobaccoGrade;
import com.ankang.entity.TobaccoPackageOutbound;
import com.ankang.service.TobaccoGradeService;
import com.ankang.service.TobaccoPackageOutboundService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 通道处理器（单个通道的核心业务逻辑）
 * 流程：IO触发→读取RFID→查询等级→判断方向→发送IO指令→更新显示器
 */
@Component
@Scope("prototype") // 关键：设置为原型作用域，每次获取都创建新实例
public class ChannelProcessor {


    private static final Logger log = LoggerFactory.getLogger(ChannelProcessor.class);

    // 移除全局读卡锁，每个通道独立处理

    // 连接状态标记
    private final AtomicBoolean ioConnected = new AtomicBoolean(false);
    private final AtomicBoolean rfidConnected = new AtomicBoolean(false);
    private final AtomicBoolean displayConnected = new AtomicBoolean(false);

    @Autowired
    private TobaccoPackageOutboundService tobaccoPackageOutboundService;

    private ChannelLevel channelLevel;
    private IOController ioController;
    private RFIDReader rfidReader;

    public void init(ChannelLevel channelLevel) {
        this.channelLevel = channelLevel;
        log.info("创建通道{}的处理器", channelLevel.getChannelId());
        this.ioController = new IOController(channelLevel);
        this.rfidReader = new RFIDReader(channelLevel);
    }

    @Autowired
    private TobaccoGradeService tobaccoGradeService;

    public ChannelLevel getChannelLevel() {
        return this.channelLevel;
    }

    public void startChannel() {
        log.info("ChannelProcessor.startChannel() 执行了");
        int channelId = channelLevel.getChannelId();
        log.info("通道{} 启动：开始监听IO设备X1信号", channelId);
        String targetGrade = channelLevel.getTargetGrade();

        // 初始化显示器
        log.info("通道{} 初始化完成，目标等级：{}", channelId, targetGrade);

        // 启动IO监听
        ioController.startListening(() -> {
            try {
                log.info("通道{} IO触发，开始处理烟包", channelId);
                processSmoke(channelId, targetGrade);
            } catch (Exception e) {
                log.error("通道{} 烟包处理异常", channelId, e);
            }
        });

        log.info("通道{} 初始化完成，连接状态：IO={}, RFID={}, 显示器={}",
                channelId, ioConnected.get(), rfidConnected.get(), displayConnected.get());
    }

    public void stopChannel() {
        ioController.stopListening();
        if (rfidReader != null) {
            rfidReader.release();
        }
        log.info("通道{} 已停止", channelLevel.getChannelId());
    }

    /**
     * 烟包处理流程（移除全局锁逻辑）
     */
//    private void processSmoke(int channelId, String targetGrade) {
//        try {
//            // 1. 读取RFID（已在RFIDReader中实现实例级锁控制）
//            String rfid = rfidReader.readRfid();
//            if (rfid == null || rfid.isEmpty()) {
//                log.warn("通道{} 未读取到RFID，跳过处理", channelId);
//                return;
//            }
//
//            // 2. 数据库查询烟叶等级
//            TobaccoGrade tobaccoGrade = tobaccoGradeService.getOne(new QueryWrapper<TobaccoGrade>().eq("rfid",rfid));
//            if (tobaccoGrade == null) {
//                log.warn("通道{} RFID:{} 未查询到烟叶等级，发送向右指令", channelId, rfid);
//                ioController.sendIoCommand(IOController.Direction.RIGHT);
//                return;
//            }
//            String actualGrade = tobaccoGrade.getLeafLevelNo();
//            log.info("通道{} 查询到烟叶等级：RFID={}，实际等级={}，目标等级={}",
//                    channelId, rfid, actualGrade, targetGrade);
//
//            // 3. 判断等级是否匹配，发送对应IO指令
//            if (targetGrade.equals(actualGrade)) {
//                log.info("通道{} 等级匹配，发送向下指令（出库）", channelId);
//                ioController.sendIoCommand(IOController.Direction.DOWN);
//
//                // 记录出库信息
//                try {
//                    TobaccoPackageOutbound record = new TobaccoPackageOutbound();
//                    record.setTobaccoGrade(actualGrade);
//                    record.setRfid(rfid);
//                    record.setChannelNumber(channelId);
//                    record.setCreateTime(new Date());
//
//                    if (tobaccoPackageOutboundService.saveOutboundRecord(record)) {
//                        log.info("通道{} 出库记录保存成功，RFID:{}", channelId, rfid);
//                    } else {
//                        log.error("通道{} 出库记录保存失败，RFID:{}", channelId, rfid);
//                    }
//                } catch (Exception e) {
//                    log.error("通道{} 保存出库记录异常，RFID:{}", channelId, rfid, e);
//                }
//            } else {
//                log.info("通道{} 等级不匹配，发送向右指令（进入下一个通道）", channelId);
//                ioController.sendIoCommand(IOController.Direction.RIGHT);
//            }
//        } catch (Exception e) {
//            log.error("通道{} 处理异常", channelId, e);
//        }
//    }


    /**
     * 烟包处理流程（移除全局锁逻辑）
     */
    private void processSmoke(int channelId, String targetGrade) {
        try {
            // 1. 读取RFID（循环读取直到成功）
            String rfid = null;
            while (true) {
                rfid = rfidReader.readRfid1();


                if (rfid != null && !rfid.isEmpty()) {
                    log.info("通道{} 成功读取到RFID: {}", channelId, rfid);
                    break;
                }
                log.warn("通道{} 未读取到RFID，将重试...", channelId);
                // 可添加短暂延迟避免CPU空转，根据实际情况调整延迟时间
                TimeUnit.MILLISECONDS.sleep(100);
            }

            // 2. 数据库查询烟叶等级
            TobaccoGrade tobaccoGrade = tobaccoGradeService.getOne(new QueryWrapper<TobaccoGrade>().eq("rfid", rfid));
            if (tobaccoGrade == null) {
                log.warn("通道{} RFID:{} 未查询到烟叶等级，发送向右指令", channelId, rfid);
                ioController.sendIoCommand(IOController.Direction.RIGHT);
                return;
            }
            String actualGrade = tobaccoGrade.getLeafLevelNo();
            log.info("通道{} 查询到烟叶等级：RFID={}，实际等级={}，目标等级={}",
                    channelId, rfid, actualGrade, targetGrade);

            // 3. 判断等级是否匹配，发送对应IO指令、、匹配多等级逻辑，只要包含查到的等级就通过
            if (targetGrade.contains(actualGrade)) {
                log.info("通道{} 等级匹配，发送向下指令（出库）", channelId);
                ioController.sendIoCommand(IOController.Direction.DOWN);

                // 记录出库信息
                try {
                    TobaccoPackageOutbound record = new TobaccoPackageOutbound();
                    record.setTobaccoGrade(actualGrade);
                    record.setRfid(rfid);
                    record.setChannelNumber(channelId);
                    record.setCreateTime(new Date());

                    if (tobaccoPackageOutboundService.saveOutboundRecord(record)) {
                        log.info("通道{} 出库记录保存成功，RFID:{}", channelId, rfid);
                    } else {
                        log.error("通道{} 出库记录保存失败，RFID:{}", channelId, rfid);
                    }
                } catch (Exception e) {
                    log.error("通道{} 保存出库记录异常，RFID:{}", channelId, rfid, e);
                }
            } else {
                log.info("通道{} 等级不匹配，发送向右指令（进入下一个通道）", channelId);
                ioController.sendIoCommand(IOController.Direction.RIGHT);
            }
        } catch (InterruptedException e) {
            log.error("通道{} 读卡等待被中断", channelId, e);
            Thread.currentThread().interrupt(); // 恢复中断状态
        } catch (Exception e) {
            log.error("通道{} 处理异常", channelId, e);
        }
    }

    public Integer getChannelId() {
        return channelLevel.getChannelId();
    }

    @PostConstruct
    public void init() {
        System.out.println("初始化操作...");
    }

    public boolean isAllConnected() {
        return ioConnected.get() && rfidConnected.get() && displayConnected.get();
    }

    public String getConnectionErrorInfo() {
        List<String> errors = new ArrayList<>();
        if (!ioConnected.get()) errors.add("IO控制器");
        if (!rfidConnected.get()) errors.add("RFID读卡器");
        if (!displayConnected.get()) errors.add("显示器");
        return errors.isEmpty() ? "无异常" : String.join("、", errors) + "连接失败";
    }

}
